#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2015  Data Enlighten Technology (Beijing) Co.,Ltd

import atexit
import json
import os
import time
import Lib.Logger.log4py as logging
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException, WebDriverException
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support.expected_conditions import presence_of_element_located
from selenium.webdriver.common.by import By
from mj_parser import common_errors


def login_on_error(func):
    def func_wrapper(self, *args, **kwargs):
        for retries in range(0, 3):
            res = func(self, *args, **kwargs)
            if res is not None:
                return res
            self.login()

    return func_wrapper


def log_error_on_none(func):
    def func_wrapper(self, *args, **kwargs):
        res = func(self, *args, **kwargs)
        if res is None:
            logging

'''
driver.execute_script(
    "localStorage.setItem('profiles', JSON.stringify([{                     " +
                        "  title: 'Selenium', hideComment: true, appendMode: '',           " +
                        "  headers: [                                                      " +
                        "  {enabled: true, name: 'user-ip', value: '35.157.132.212'},      " +
                        "  ],                                                              " +
                        "  respHeaders: [],                                                " +
                        "  filters: []                                                     " +
                        "}]));                                                             ")
                        '''
# 必须初始化执行，否则无法产生instance用于load cookie


ajax_js = '''
function get_or_create_div(id) {{
    var resultElem = document.body.querySelector('#'+id);
    if (resultElem != null) {{
        resultElem.textContent = '';
    }} else {{
        resultElem = document.createElement("div");
        resultElem.id = id; 
        var textNode = document.createTextNode('');
        resultElem.appendChild(textNode);
        document.body.appendChild(resultElem);    
    }}
    return resultElem;
}}

var oReq = new XMLHttpRequest();
var method = "{0}";
var url = "{1}";
var contentType = '{2}'; 
var payload = '{3}';

oReq.open(method, url, false);

if (contentType != '') {{ 
    oReq.setRequestHeader("Content-Type", contentType);
}}

if (payload == '') {{
    payload = null;
}}

oReq.send(payload)

var resultElem = get_or_create_div('custom-result');
var statusElem = get_or_create_div('custom-status');

statusElem.textContent = oReq.status;
if (oReq.status < 300) {{
    resultElem.textContent = oReq.responseText;
}} else {{
    resultElem.textContent = "";
}}
'''


class LandRoverWebSource:
    URL = 'https://epc.jlr-apps.com/api/vin/decode/11/{0}?languageId=1&searchType=VIN&t={1}'
    LOGIN_URL = 'https://epc.jlr-apps.com/login'

    def __init__(self, root_path='.'):
        self.logger = logging.get_logger('crawler', 'LandroverWebSource')
        self.root_path = root_path
        self.conf_path = os.path.join(root_path, 'conf')
        self.cookie_file = os.path.join(self.conf_path, 'landrover_cookie.txt')
        self.data_path = os.path.join(root_path, "data")
        self.driver = self.init_chrome_driver()
        atexit.register(self.cleanup)

    def init_chrome_driver(self):
        # 设置http header
        chrome_log = os.path.join(self.data_path, "chrome.log")
        bin_path = os.path.join(self.root_path, 'bin')
        ext_path = os.path.join(bin_path, 'extension', 'idgpnmonknjnojddfkpgkljpfnnfcklj_2_1_2.crx')
        chrome_path = os.path.join(bin_path, 'chromedriver.exe')

        options = webdriver.ChromeOptions()
        options.add_extension(ext_path)
        options.add_argument('--proxy-server=http://101.132.46.34:5870')
        options.add_argument('Connection="keep-alive"')
        options.add_argument('Key="f3a9b43d-77d6-4f9e-b07b-0039a41712ca"')
        options.add_argument('ClientSign="6c2912669b37591b0e96f2bf08977efd"')
        options.add_argument(
            'user-agent="Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36"')
        options.add_argument('--user-data-dir={0}/users'.format(bin_path))

        prefs = {"modifyheaders.config.active": True,
                 "modifyheaders.config.alwaysOn": True,
                 "modifyheaders.config.openNewTab": True,
                 "modifyheaders.start": True,
                 "modifyheaders.headers.count": 1,
                 "modifyheaders.headers.action0": 'Add',
                 "modifyheaders.headers.name0": 'somanasdf',
                 "modifyheaders.headers.value0": 'asfdsaf',
                 "modifyheaders.headers.enabled0": True
                 }

        # options.add_experimental_option("prefs", prefs)

        return webdriver.Chrome(chrome_path, chrome_options=options, service_args=["--verbose", "--log-path={0}".format(chrome_log)])

    def exec_ajax(self, script):
        try:
            self.driver.execute_script(script)
            status = self.driver.find_element_by_css_selector('#custom-status')
            result = self.driver.find_element_by_css_selector('#custom-result')
        except NoSuchElementException as e:
            self.logger.error("Cannot find custom-result div, meaning ajax call failed")
            return None
        except WebDriverException as e2:
            self.logger.error(str(e2))
            return None

        if int(status.text) != 200:
            self.logger.error("Ajax call failed: " + status.text)
            return None
            
        if not result.text:
            self.logger.error("Empty response: " + status.text)
            return None

        self.logger.info("+++" + result.text)
        return json.loads(result.text)

    def request_post(self, url, content_type, payload):
        self.logger.info("POST: " + url)
        payload_str = json.dumps(payload)
        script = ajax_js.format("POST", url, content_type, payload_str)
        return self.exec_ajax(script)

    def request_get(self, url):
        self.logger.info("GET: " + url)
        script = ajax_js.format("GET", url, '', '')
        return self.exec_ajax(script)

    def search_vin(self, str_vin):
        try:
            cur_url = self.URL.format(str_vin, int(round(time.time() * 1000)))
            self.driver.get(cur_url)

            if self.driver.current_url.find(cur_url) < 0:
                # cookie 失效,验权重试一次
                if self.login():
                    self.driver.get(cur_url)
                    if self.driver.current_url.find(cur_url) < 0:
                        self.logger.error("Login failed")
                        exit()

            vin_file = os.path.join(self.data_path, '{0}.html'.format(str_vin))
            with open(vin_file, 'wb') as fo:
                fo.write(self.driver.page_source.encode('utf-8'))

            return vin_file
        except Exception as ex:
            self.logger.error(ex)
        return None

    def get_data(self, str_vin, brand, group):

        # 实例
        # driver.get("https://epc.jlr-apps.com/api/vin/decode/11/SALVA2BG2DH800209?languageId=1&searchType=VIN&t=1513847130415")
        vin_file = self.search_vin(str_vin)
        if vin_file is None:
            return common_errors.ERR_TCP_ERROR, None
        return common_errors.ERR_SUCCESS, vin_file

    def login(self):
        self.driver.get(LandRoverWebSource.LOGIN_URL)
        WebDriverWait(self.driver, 90).until(
            presence_of_element_located((By.CSS_SELECTOR, "div.full-width.header-title")),
        )
        return True

    def cleanup(self):
        if self.driver is not None:
            self.driver.quit()


if __name__ == '__main__':
    lr = LandRoverWebSource()
    # 无效vin
    lr.get_data('SAL1A2BG2DH800200', '', '')
    # 有效vin
    lr.get_data('SALVA2BG2DH800209', '', '')